
package control;

import controladoresJpa.exceptions.IllegalOrphanException;
import controladoresJpa.exceptions.NonexistentEntityException;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import model.AtributoMER;
import model.AtributoMR;
import model.DicionarioMER;
import model.DicionarioMR;
import model.Entidade;
import model.Esquema;
import model.Projetista;
import model.Relacionamento;
import model.Tabela;
import service.AtributoMERService;
import service.AtributoMRService;
import service.DicionarioMERService;
import service.DicionarioMRService;
import service.EntidadeService;
import service.EsquemaService;
import service.ProjetistaService;
import service.RelacionamentoService;
import service.TabelaService;
import java.util.logging.Logger;



/**
 * Classe controladora para o módulo de gerênciamento do sistema
 * @author Eduardo, Maylon e Kamilla
 */
public class ManagementController implements Serializable{

    private ProjetistaService ps;
    private EsquemaService es;
    private DicionarioMRService dmrs;
    private DicionarioMERService dmers; 
    private AtributoMRService amrs;
    private TabelaService ts;
    private AtributoMERService amers;
    private RelacionamentoService rs;
    private EntidadeService ents;
    private MRController control; 
    private static Logger log = Logger.getLogger(ManagementController.class.getName());
    
    /**
     * Método Construtor
     */
  public ManagementController() {
        ps = new ProjetistaService();
        es = new EsquemaService();
        
        dmrs = new DicionarioMRService();
        dmers = new DicionarioMERService();
        
        amrs = new AtributoMRService();
        ts = new TabelaService();
        
        amers = new AtributoMERService();
        rs = new RelacionamentoService();
        ents = new EntidadeService();
          
        control = new MRController();
    }
    
  /**
   * Controla o  processo de salvar um projetista
   * @param p 
   */
  public void salvarProjetista( Projetista p ){
        ps.salvar(p);
        log.fine("Projetista: "+ p.getNome()+", "+p.getEMail()+" salvo com sucesso");
        
    }
  
   /**
   * Controla o  processo de exclusão de um projetista
   * @param p 
   */
  public void excluirProjetista(Projetista p) {
       Projetista proj= ps.recuperarDoBancoDados(p);
       List list = proj.getEsquemaList();
       Iterator i = list.iterator();
       while(i.hasNext()){
           Esquema esq = (Esquema)i.next();
           esq.getProjetistaList().remove((Object)proj);
           es.salvar(esq);
           log.fine("Projetista: "+ proj.getNome()+", "+proj.getEMail()+" removido com com sucesso do esquema: "+ esq.getNome());
       }
       proj.getEsquemaList().clear();
       ps.excluir(p);
       log.info("Projetista: "+ proj.getNome()+", "+proj.getEMail()+" excluido com com sucesso do banco de dados ");
   }
   
  /**
   * Chama a listagem de projetistas
   * @return 
   */
  public List recarregarProjetista(){
       return ps.recarregar();
   }
  
  /**
   * Controla o  processo de Buscar no BD
   * @param Email
   * @return 
   */
  public Projetista recuperarProjetistaDoBancoDados(String Email){
      return ps.recuperarDoBancoDados(new Projetista(Email));
  }
   
  /**
   * Controla o  processo de salvar um esquema existente
   * @param e 
   */
  public void salvarEsquemaExistente( Esquema e ){
        es.editar(e);
        log.fine("Salvo esquema existente: "+e.getNome());
    }
    
  /**
   * Controla o  processo de salvar um novo esquema
   * @param e 
   */
  public void salvarNovoEsquema(Esquema e){
        if(!es.encontrado(e)){
            es.salvar(e);
            //Um esquema podera ter apenas dois dicionários, sendo um do MER e outro do MR.
            DicionarioMER dmer = new DicionarioMER(e);
            DicionarioMR dmr=new DicionarioMR(e);
            dmers.salvar(dmer);
            dmrs.salvar(dmr);
            e.getDicionarioMERList().add(dmer);
            e.getDicionarioMRList().add(dmr);
            es.editar(e);
            log.fine("Criacao do novo esquema: "+e.getNome() +" Com 2 dicionáriors: um MER e um MR");
        }
        
    }
   
  /**
   * Controla o  processo de excluir um dicionário MR
   * @param ddmr 
   */
  private void excluirDicionarioMR(DicionarioMR ddmr) {
            DicionarioMR d= dmrs.recuperarDoBancoDados(ddmr) ;
            List list = d.getAtributoMRList();
            Iterator i = list.iterator();
            //Excluindo os Atributos
            while(i.hasNext()){
                AtributoMR a = (AtributoMR)i.next();
                control.excluirAtributo(a);
                log.fine("Exclusão do elemento: "+ a.getNome()+", do dicionário MR do esquema:"+d.getNomeEsquema());
            }
            list = d.getTabelaList();
            i = list.iterator();
            //Excluindo Tabelas
            while(i.hasNext()){
                Tabela t =(Tabela)i.next();
                ts.excluir(t);
                log.fine("Exclusão da tabela: "+ t.getNome()+", do dicionário MR do esquema:"+d.getNomeEsquema());
            }
            dmrs.excluir(ddmr);
            log.info("Exclusão do dicionário MR do esquema:"+d.getNomeEsquema());
   }
  
   /**
   * Controla o  processo de exclusão um dicionário MR
   * @param ddmer 
   */
  private void excluirDicionarioMER(DicionarioMER ddmer){
            DicionarioMER d= dmers.recuperarDoBancoDados(ddmer) ;
            List list = d.getAtributoMERList();
            Iterator i = list.iterator();
            //Excluindo os Atributos
            while(i.hasNext()){
                AtributoMER a = (AtributoMER)i.next();
                amers.excluir(a);
            }
            list = d.getEntidadeList();
            i = list.iterator();
            //Excluindo os Entidades
            while(i.hasNext()){
                Entidade t =(Entidade)i.next();
                ents.excluir(t);
            }
            list = d.getRelacionamentoList();
            i = list.iterator();
            //Excluindo Relacionamento
            while(i.hasNext()){
                Relacionamento t =(Relacionamento)i.next();
                rs.excluir(t);
            }
            dmers.excluir(ddmer);
   }

  /**
   * Controla o  processo de exclusão um esquema
   * @param ddmer 
   */
  public void excluirEsquema(Esquema e) {
            Esquema esq= es.recuperarDoBancoDados(e);
            List list = esq.getDicionarioMERList();
            Iterator i = list.iterator();
            //Excluindo os DDs do MER
            while(i.hasNext()){
                DicionarioMER ddmer = (DicionarioMER)i.next();
                this.excluirDicionarioMER(ddmer);
            }
            list = esq.getDicionarioMRList();
            i = list.iterator();
            //Excluindo os DDs do MR
            while(i.hasNext()){
                DicionarioMR ddmr = (DicionarioMR)i.next();
                this.excluirDicionarioMR(ddmr);
            }
            //Desassociando os Projetistas do Esquema
            list = esq.getProjetistaList();
            while(i.hasNext()){
                Projetista p = (Projetista)i.next();
                this.removerProjetistaDoEsquema(p, esq);
            }
           esq.getDicionarioMERList().clear();
           esq.getDicionarioMRList().clear();
           esq.getProjetistaList().clear();
           es.excluir(esq);
           log.info("Exclusão do esquema finalizada:" + e.getNome());
   }
   
  /**
   * Terna uma lista de esquemas
   * @return 
   */
  public List recarregarEsquema(){
       return es.recarregar();
   }
  
   /**
   * Controla o  processo da adição de um Projetista a um esquema
   * @param proj
   * @param esq 
   */
  public void adicionarProjetistaAoEsquema(Projetista proj, Esquema esq) {
        Projetista p = ps.recuperarDoBancoDados(proj);
        Esquema e = es.recuperarDoBancoDados(esq);
        if(p!=null && e!=null){
              List projetistas= e.getProjetistaList();
              Iterator i = projetistas.iterator();
              boolean facoParte = false;
              while(i.hasNext()){
                  Projetista projetistaEsquema = (Projetista)i.next();
                  if(projetistaEsquema.getEMail().equals(p.getEMail()))
                      facoParte=true;
              }
              if(!facoParte){
              p.getEsquemaList().add(e);
              e.getProjetistaList().add(p);
              this.salvarProjetista(p);
              this.salvarEsquemaExistente(e);
              log.info("Projetista: "+ p.getNome()+" adicionado com suceso ao esquema: "+ e.getNome());
        }
   }
  }
   
  /**
   * Controla o  processo da remoção de um Projetista a um esquema
   * @param proj
   * @param esq 
   */
  public void removerProjetistaDoEsquema(Projetista proj, Esquema esq){
      if(ps.encontrado(proj)&&es.encontrado(esq)){
          Projetista p = ps.recuperarDoBancoDados(proj);
          Esquema e = es.recuperarDoBancoDados(esq);
          p.getEsquemaList().remove((Object)e);
          e.getProjetistaList().remove((Object)p);
          this.salvarEsquemaExistente(e);
          this.salvarProjetista(p);
          log.info("Projetista: "+ p.getNome()+" removido com sucesso de esquema: "+ e.getNome());
      }
   }

  /**
   * Recupera os esquemas salvos no BD
   * @param nome
   * @return 
   */
  public Esquema recuperarEsquemaDoBancoDados(String nome){
      return es.recuperarDoBancoDados(new Esquema(nome));
  }
  /**
   * Valida o Login de um projetista no sistema
   * @param email
   * @param senha
   * @return 
   */
  public String efetuarLogin(String email, String senha){
          Projetista p = new Projetista();
          p.setEMail(email);
          p.setSenha(senha);
          Projetista registrado = ps.recuperarDoBancoDados(p);
          if(registrado!=null && registrado.getSenha().equals(senha)){
              log.info("Projetista: "+ p.getNome()+" Logado com sucesso ");
              return "sucesso";
          }
          log.info("Projetista: "+ p.getNome()+" Não foi Logado ");
          return "falha";
      }

      
      
   }



   
    
    
    
    
    
